package edu.bath.sensors.powersensor;

import edu.bath.sensorframework.sensor.Sensor;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.jivesoftware.smack.XMPPException;

public class PowerSensor extends Sensor {
	private SerialPort serialPort;
	private BufferedReader br;
	private boolean alive = true;
	
	private String currentLocation;
	private String primaryHandle;
	
	public void close() {
		serialPort.close();
	}
	
	public PowerSensor(String serverAddress, String serverName, String id, String password, String nodeName, String currentLocation, String primaryHandle) throws XMPPException {
		super(serverAddress, serverName, id, password, nodeName);
		this.currentLocation = currentLocation;
		this.primaryHandle = primaryHandle;
	}
	
	public static void main(String[] args) throws Exception {
		PowerSensor ps = new PowerSensor("laptop", "laptop", "powersensor", "bobbo", "powerSensor", "adan", "0EAS");
		System.out.println("Created PowerSensor, now entering its logic!");
		ps.run("/dev/ttyUSB0");
		ps.close();
	}

	public void run(String id) throws XMPPException {
		try {
		CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(id);
		if (portIdentifier.isCurrentlyOwned()) {
			throw new RuntimeException("Port already in use!");
		}
		System.out.println("Got COM port!");
		
		serialPort = (SerialPort) portIdentifier.open("PowerSensor", 2048);
		serialPort.setSerialPortParams(57600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
		br = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
		br.readLine(); // we may attach to the port half way through a transmission, so we need to discard the first of whatever we receive
		} catch(Exception e) {
//			Log.console("Exception setting up port.");
		}
		System.out.println("COM port set up!");
		
		final List<PowerReading> readings = Collections.synchronizedList(new ArrayList<PowerReading>(10));
		Runnable publishThread = new Runnable() {
			@Override
			public void run() {
//				long time = System.currentTimeMillis();
				List<PowerReading> readingsStore = new ArrayList<PowerReading>(10);
				while(alive) {
//					if((System.currentTimeMillis() - time) < 10000)
//						continue;
					
					if(readings.size() == 0)
						continue;
					
					readingsStore.clear();
					synchronized(readings) {
						readingsStore.addAll(readings);
						readings.clear();
					}
					
					for(PowerReading pr : readingsStore) {
						try {
							System.out.println("Publishing data (temp is "+pr.getTemperature()+")");
							publish(pr.toDataReadingTemp());
							publish(pr.toDataReadingPwr());
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
					
//					time = System.currentTimeMillis();
					try {
						Thread.sleep(10000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		};
		Thread pThread = new Thread(publishThread);
		pThread.start();
		
		while(alive) {
			try {
				String data = "";
				while(br.ready())
					data = br.readLine();
				PowerReading pr = PowerReading.fromXML(data);
				System.out.println("Got temp data.. "+pr.getTemperature());
				pr.setCurrentLocation(currentLocation);
				pr.setPrimaryHandle(primaryHandle);
				readings.add(pr);
				Thread.sleep(60*1000);
			} catch (Exception e) {
//				Log.console ("Exception reading data");
				continue;
			}
		}
		
		cleanup();
	}
}
